package com.jsu.user.service.impl;

import cn.hutool.core.codec.Base64;
import cn.hutool.http.HttpUtil;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.jsu.user.mapper.WebUserMapper;
import com.jsu.user.service.AppLoginService;
import lombok.Value;
import lombok.extern.slf4j.Slf4j;
import org.apache.hadoop.fs.shell.find.Result;
import org.example.model.common.dtos.ResponseResult;
import org.example.model.common.enums.RedisCodeEnum;
import org.example.model.common.enums.WebHttpCodeEnum;
import org.example.model.user.dto.AppLoginDto;
import org.example.model.user.dto.WXAuth;
import org.example.model.user.pojo.User;
import org.example.utils.common.WebJwtUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;

import javax.crypto.Cipher;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;
import java.security.spec.AlgorithmParameterSpec;
import java.util.HashMap;
import java.util.Objects;
import java.util.UUID;
import java.util.concurrent.TimeUnit;

import static org.example.model.common.enums.RedisCodeEnum.LOGIN;

@Service
@Slf4j
public class AppLoginServiceImpl extends ServiceImpl<WebUserMapper, User> implements AppLoginService {
    @Autowired
    private StringRedisTemplate redisTemplate;
    @Autowired
    private WebUserMapper userMapper;
    private final static String appid = "wx37e98bfa9748170d";
    private final static String secret = "1490cb27ae76200a86b235e2e8d9beb9";
    @Override
    public ResponseResult getSessionId(String code) {
        String url = "https://api.weixin.qq.com/sns/jscode2session?appid={0}&secret={1}&js_code={2}&grant_type=authorization_code";
        String replaceUrl = url.replace("{0}", appid).replace("{1}", secret).replace("{2}", code);
        String res = HttpUtil.get(replaceUrl);
        String s = UUID.randomUUID().toString();
        redisTemplate.opsForValue().set(RedisCodeEnum.WX_SESSION_ID + s, res);
        return ResponseResult.okResult(s);
    }
    @Override
    public ResponseResult authLogin(WXAuth wxAuth) {
        try {
            String wxRes = wxDecrypt(wxAuth.getEncryptedData(), wxAuth.getSessionId(), wxAuth.getIv());
            log.info("用户信息："+wxRes);
            //用户信息：{"openId":"o2ttv5L2yufc4-sVoSPhTyUnToY60","nickName":"juana","gender":2,"language":"zh_CN","city":"Changsha","province":"Hunan","country":"China","avatarUrl":"头像链接","watermark":{"timestamp":1631617387,"appid":"应用id"}}
            User wxUserInfo = JSON.parseObject(wxRes,User.class);
            // 业务操作：你可以在这里利用数据 对数据库进行查询， 如果数据库中没有这个数据，就添加进去，即实现微信账号注册
            User user = userMapper.selectByPhone(wxUserInfo.getTel());
            if (Objects.isNull(user)) {
                userMapper.insert(wxUserInfo);
            }else {
                // 如果数据库中已经有这个数据，就更新
                userMapper.update(null, new QueryWrapper<User>().eq("tel", wxUserInfo.getTel()));
            }
            // 如果是已经注册过的，就利用数据，生成jwt 返回token，实现登录状态
            //根据手机号生成token
            String jwt = WebJwtUtil.getToken(Long.valueOf(user.getTel()));
            log.info("生成token:"+jwt);
            //返回token和用户信息
            user.setPassword("");
            user.setSalt("");
            AppLoginDto appLoginDto = new AppLoginDto(user,jwt);
            return ResponseResult.okResult(appLoginDto);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return ResponseResult.errorResult(WebHttpCodeEnum.FAIL);
    }

    private String wxDecrypt(String encryptedData, String sessionId, String vi) throws Exception {
        // 开始解密
        String json =  redisTemplate.opsForValue().get(RedisCodeEnum.WX_SESSION_ID + sessionId);
        log.info("之前存储在redis中的信息："+json);
        //之前存储在redis中的信息：{"session_key":"G59Evf\/Em54X6WsFsrpA1g==","openid":"o2ttv5L2yufc4-VoSPhTyUnToY60"}
        JSONObject jsonObject = JSON.parseObject(json);
        String sessionKey = (String) jsonObject.get("session_key");
        byte[] encData = cn.hutool.core.codec.Base64.decode(encryptedData);
        byte[] iv = cn.hutool.core.codec.Base64.decode(vi);
        byte[] key = Base64.decode(sessionKey);
        AlgorithmParameterSpec ivSpec = new IvParameterSpec(iv);
        Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
        SecretKeySpec keySpec = new SecretKeySpec(key, "AES");
        cipher.init(Cipher.DECRYPT_MODE, keySpec, ivSpec);
        return new String(cipher.doFinal(encData), "UTF-8");
    }
}
